﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMStudio.Common;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using AMStudio.DelegateDispather;
using System.IO.Ports;
using System.Threading;

namespace AMStudio.Driver
{
    public class ECheckDriver : IAutomationDriver
    {
        protected ExceptionManager ExManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

        private ECheckConfig myConfig = null;

        private DelegateDispather.IEventClient eventClient;
        public DelegateDispather.IEventClient EventClient
        {
            get { return eventClient; }
            set { eventClient = value; }
        }
        private ECheck hardwaredriver;
        private bool alreadyinitialized = false;
        private IExecuteReader result = new ExecuteReader(false);

        private String hardwareName = "ECHECK";
        public String HardwareName
        {
            get { return hardwareName; }
            set { hardwareName = value; }
        }
        private String hardwareEvent = "ECHECK_RET";
        public String HardwareEvent
        {
            get { return hardwareEvent; }
            set { hardwareEvent = value; }
        }

        public void Initialize(IEventManager eventManager, ECheckConfig config)
        {
            myConfig = config;
            hardwaredriver = new ECheck();
            hardwaredriver.OnConnectClosed += new ConnectClosedHandler(hardwaredriver_OnConnectClosed);
            hardwaredriver.OnConnected += new ConnectedHandler(hardwaredriver_OnConnected);
            eventClient = new EventClient(eventManager);
            this.hardwareEvent = config.HardwareEvent;
            this.hardwareName = config.HardwareName;
        }
        public virtual int ExecuteNonQuery(string command, params object[] parameters)
        {
            return -1;
        }
        public virtual IExecuteReader ExecuteReader(string command, params object[] parameters)
        {
            _Received_Data = null;
            result.Success = false;
            try
            {
                switch (command)
                {
                    case "INIT":
                        #region Command "INIT"
                        {
                            if (!alreadyinitialized)
                            {
                                this.Initialize((IEventManager)parameters[0], (ECheckConfig)parameters[1]);
                                if (!hardwaredriver.Initialize())
                                {
                                    Logger.Write("System Error! (Can not connect the laser controller!)");
                                    hardwaredriver.Close();
                                }
                                else
                                {
                                    result.Success=true;
                                    alreadyinitialized = true;                          
                                }
                            }
                        }
                        #endregion
                        break;
                    case "EXIT":
                        #region Command "DISCONNECT"
                        result.Success = true;
                        if (alreadyinitialized)
                        {
                            hardwaredriver.Close();
                            alreadyinitialized = false;
                        }
                        #endregion
                        break;
                    case "CONNECT_STATUS":
                        #region Command "CONNECT_STATUS"
                        {
                            if (alreadyinitialized)
                            {
                                result.Result = true;
                                result.Success = true;
                            }
                            else
                            {
                                result.Result = false;
                                result.Success = true;
                            }
                        }
                        #endregion
                        break;
                    case "LOADCANDLL":
                        #region Command "LOADCANDLL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string dllName = parameters[0].ToString();
                                int ret = this.hardwaredriver.LoadCanDll(dllName);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "FREECANDLL":
                        #region Command "FREECANDLL"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                int ret = this.hardwaredriver.FreeCanDll();
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret });
                            }
                        }
                        #endregion
                        break;
                    case "GETECUSN":
                        #region Command "GETECUSN"
                        {
                            if (alreadyinitialized)
                            {
                                _Current_Command = command;
                                string sn, errMsg;
                                int size;
                                int ret = this.hardwaredriver.GetEcuSN(out sn, out size, out errMsg);
                                if (ret < 0)
                                {
                                    result.Success = false;
                                }
                                else
                                {
                                    result.Success = true;
                                }
                                result.Result = (object)(new object[] { ret, sn, size, errMsg });
                            }
                        }
                        #endregion
                        break;
                    default:
                        break;
                }           
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
                alreadyinitialized = false;
                RaiseEvent("DISCONNECT", true, null);
                if (hardwaredriver != null)
                    hardwaredriver.Close();
            }
            return result;
        }
        private void hardwaredriver_OnConnected(object sender, int e)
        {
            RaiseEvent("CONNECTED", true, null);
        }

        private void hardwaredriver_OnConnectClosed(object sender, int e)
        {
            alreadyinitialized = false;

            RaiseEvent("DISCONNECTED", true, null);
        }

        #region Variable, common for each hardware, hardware related

        private AutoResetEvent _Signal_Command_Finished = new AutoResetEvent(false);
        private string[] _Received_Data = null;
        private String _Current_Command = String.Empty;
        private String _Current_Tag = string.Empty;
        private bool _CameraRequest_Result = false;
        private string _2DCode=string.Empty;
        #endregion

        public void RaiseEvent(string command, bool status, object result)
        {
            StationEventArgs arg = new StationEventArgs(hardwareName, command, status, result);
            eventClient.RaiseEvent(hardwareEvent, arg);
        }
    }
}
